/**
 * @class EventResult 事件结果统计
 */
const BaseMod = require('./base');
const Platform = require('./platform');
const Channel = require('./channel');
const Version = require('./version');
const EventLog = require('./eventLog');
const { DateTime } = require('../lib');
module.exports = class EventResult extends BaseMod {
    constructor() {
        super();
        this.tableName = 'event-result';
        this.platforms = [];
        this.channels = [];
        this.versions = [];
    }

    /**
     * 事件数据统计
     * @param {String} type 统计类型 hour：实时统计 day：按天统计，week：按周统计 month：按月统计
     * @param {Date|Time} date 指定日期或时间戳
     * @param {Boolean} reset 是否重置，为ture时会重置该批次数据
     */
    async stat(type, date, reset) {
        const allowedType = ['day'];
        if (!allowedType.includes(type)) {
            return {
                code: 1002,
                msg: 'This type is not allowed',
            };
        }
        this.fillType = type;
        const dateTime = new DateTime();
        const dateDimension = dateTime.getTimeDimensionByType(type, -1, date);
        this.startTime = dateDimension.startTime;
        this.endTime = dateDimension.endTime;
        if (this.debug) {
            console.log('dimension time', this.startTime + '--' + this.endTime);
        }

        // 查看当前时间段日志是否已存在,防止重复生成
        if (!reset) {
            const checkRes = await this.getCollection(this.tableName)
                .where({
                    start_time: this.startTime,
                    end_time: this.endTime,
                })
                .get();
            if (checkRes.data.length > 0) {
                console.log('event log have existed');
                return {
                    code: 1003,
                    msg: 'This log have existed',
                };
            }
        } else {
            const delRes = await this.delete(this.tableName, {
                start_time: this.startTime,
                end_time: this.endTime,
            });
            console.log('delete old data result:', JSON.stringify(delRes));
        }

        // 数据获取
        this.eventLog = new EventLog();
        const statRes = await this.aggregate(this.eventLog.tableName, {
            project: {
                appid: 1,
                version: 1,
                platform: 1,
                channel: 1,
                event_key: 1,
                device_id: 1,
                create_time: 1,
            },
            match: {
                create_time: {
                    $gte: this.startTime,
                    $lte: this.endTime,
                },
            },
            group: {
                _id: {
                    appid: '$appid',
                    version: '$version',
                    platform: '$platform',
                    channel: '$channel',
                    event_key: '$event_key',
                },
                event_count: {
                    $sum: 1,
                },
            },
            sort: {
                event_count: 1,
            },
            getAll: true,
        });

        let res = {
            code: 0,
            msg: 'success',
        };
        if (this.debug) {
            console.log('statRes', JSON.stringify(statRes));
        }
        if (statRes.data.length > 0) {
            this.fillData = [];
            for (const i in statRes.data) {
                await this.fill(statRes.data[i]);
            }
            if (this.fillData.length > 0) {
                res = await this.batchInsert(this.tableName, this.fillData);
            }
        }
        return res;
    }

    /**
     * 事件统计数据填充
     * @param {Object} data 数据集合
     */
    async fill(data) {
        // 平台信息
        let platformInfo = null;
        if (this.platforms && this.platforms[data._id.platform]) {
            //暂存下数据，减少读库
            platformInfo = this.platforms[data._id.platform];
        } else {
            const platform = new Platform();
            platformInfo = await platform.getPlatformAndCreate(data._id.platform, null);
            if (!platformInfo || platformInfo.length === 0) {
                platformInfo._id = '';
            }
            this.platforms[data._id.platform] = platformInfo;
            if (this.debug) {
                console.log('platformInfo', JSON.stringify(platformInfo));
            }
        }

        // 渠道信息
        let channelInfo = null;
        const channelKey = data._id.appid + '_' + platformInfo._id + '_' + data._id.channel;
        if (this.channels && this.channels[channelKey]) {
            channelInfo = this.channels[channelKey];
        } else {
            const channel = new Channel();
            channelInfo = await channel.getChannelAndCreate(data._id.appid, platformInfo._id, data._id.channel);
            if (!channelInfo || channelInfo.length === 0) {
                channelInfo._id = '';
            }
            this.channels[channelKey] = channelInfo;
            if (this.debug) {
                console.log('channelInfo', JSON.stringify(channelInfo));
            }
        }

        // 版本信息
        let versionInfo = null;
        const versionKey = data._id.appid + '_' + data._id.platform + '_' + data._id.version;
        if (this.versions && this.versions[versionKey]) {
            versionInfo = this.versions[versionKey];
        } else {
            const version = new Version();
            versionInfo = await version.getVersionAndCreate(data._id.appid, data._id.platform, data._id.version);
            if (!versionInfo || versionInfo.length === 0) {
                versionInfo._id = '';
            }
            this.versions[versionKey] = versionInfo;
            if (this.debug) {
                console.log('versionInfo', JSON.stringify(versionInfo));
            }
        }

        const matchCondition = data._id;
        Object.assign(matchCondition, {
            create_time: {
                $gte: this.startTime,
                $lte: this.endTime,
            },
        });
        if (this.debug) {
            console.log('matchCondition', JSON.stringify(matchCondition));
        }

        // 触发事件设备数统计
        const statEventDeviceRes = await this.aggregate(this.eventLog.tableName, {
            project: {
                appid: 1,
                version: 1,
                platform: 1,
                channel: 1,
                event_key: 1,
                device_id: 1,
                create_time: 1,
            },
            match: matchCondition,
            group: [
                {
                    _id: {
                        device_id: '$device_id',
                    },
                },
                {
                    _id: {},
                    total_devices: {
                        $sum: 1,
                    },
                },
            ],
        });

        let eventDeviceCount = 0;
        if (statEventDeviceRes.data.length > 0) {
            eventDeviceCount = statEventDeviceRes.data[0].total_devices;
        }

        // 触发事件用户数统计
        const statEventUserRes = await this.aggregate(this.eventLog.tableName, {
            project: {
                appid: 1,
                version: 1,
                platform: 1,
                channel: 1,
                event_key: 1,
                uid: 1,
                create_time: 1,
            },
            match: {
                ...matchCondition,
                uid: {
                    $ne: '',
                },
            },
            group: [
                {
                    _id: {
                        uid: '$uid',
                    },
                },
                {
                    _id: {},
                    total_users: {
                        $sum: 1,
                    },
                },
            ],
        });

        let eventUserCount = 0;
        if (statEventUserRes.data.length > 0) {
            eventUserCount = statEventUserRes.data[0].total_users;
        }

        const datetime = new DateTime();
        const insertParams = {
            appid: data._id.appid,
            platform_id: platformInfo._id,
            channel_id: channelInfo._id,
            version_id: versionInfo._id,
            event_key: data._id.event_key,
            event_count: data.event_count,
            device_count: eventDeviceCount,
            user_count: eventUserCount,
            dimension: this.fillType,
            stat_date: datetime.getDate('Ymd', this.startTime),
            start_time: this.startTime,
            end_time: this.endTime,
        };
        this.fillData.push(insertParams);
        return insertParams;
    }
};
